<?php

namespace common\rest;

use Yii;
use yii\web\Response;
use yii\web\HttpException;
use yii\helpers\Inflector;
use yii\helpers\ArrayHelper;
use yii\filters\ContentNegotiator;
use common\filters\Cors;
use yii\filters\RateLimiter;
use common\filters\AccessControl;
use common\filters\HttpBearerAuth;
use common\filters\VerbFilter;

/**
 * Controller is the base class for RESTful API controller classes.
 *
 * @author emhome <emhome@163.com>
 * @since 1.0
 * @property int $build
 * @property mixed $user
 */
class Controller extends \yii\rest\Controller {

    /**
     * @var boolean 是否检测访问token
     */
    public $filterAccessToken = true;

    /**
     * @var array This Application's Serializer Configures.
     */
    public $serializer = [
        'class' => 'common\rest\Serializer',
        'collectionEnvelope' => 'items',
        'linksEnvelope' => 'links',
        'metaEnvelope' => 'meta',
    ];

    /**
     * @var boolean 是否检测访问token
     */
    public $rateLimiter = [
        'class' => RateLimiter::class,
    ];

    /**
     * @var array This Application's Serializer Configures.
     */
    public $authenticator = [
        'class' => HttpBearerAuth::class,
    ];

    /**
     * 处理Auth授权验证行为
     *
     * @return array $behaviors
     */
    public function behaviors() {
        $behaviors = [
            'contentNegotiator' => [
                'class' => ContentNegotiator::class,
                'formats' => [
                    'application/json' => Response::FORMAT_JSON,
                ],
            ],
            'corsFilter' => [
                'class' => Cors::class,
            ],
            'verbFilter' => [
                'class' => VerbFilter::class,
                'actions' => $this->verbs(),
            ],
        ];
        if ($this->authenticator) {
            $this->authenticator['filterAccessToken'] = $this->filterAccessToken;
            $behaviors['authenticator'] = $this->authenticator;
        }
        if ($this->rateLimiter) {
            $behaviors['rateLimiter'] = $this->rateLimiter;
        }
        $rules = $this->rules();
        if ($rules !== null) {
            $behaviors['access'] = [
                'class' => AccessControl::class,
                'rules' => $rules,
            ];
        }
        return $behaviors;
    }

    /**
     * @inheritdoc
     */
    protected function rules() {
        return null;
    }

    /**
     * @inheritdoc
     */
    protected function verbs() {
        return [
            'index' => ['GET', 'HEAD'],
            'list' => ['GET', 'HEAD'],
            'view' => ['GET', 'HEAD'],
            'create' => ['POST'],
            'update' => ['POST'],
            'delete' => ['POST'],
        ];
    }

    /**
     * This Application's BuildNO.
     *
     * @return integer 版本号
     */
    public function getBuild() {
        return ArrayHelper::getValue(Yii::$app->params, 'build', -1);
    }

    /**
     * 记录日志
     *
     * @param $prefix
     * @param $content
     */
    public static function log($prefix, $content) {
        $message = Inflector::id2camel($prefix);
        Yii::info([
            $message,
            $content,
        ]);
    }

    /**
     * 获取当前登录用户
     */
    public function getUser() {
        return Yii::$app->user->identity;
    }

    /**
     * 显示flash信息
     *
     * @param string $message 信息显示内容
     * @param mixed $extras 信息显示类型, ['info', 'success', 'error', 'warning']
     * @param integer $code 跳转地址
     * @throws HttpException
     */
    public static function error($message, $extras = null, $code = 428) {
        if ($extras) {
            if (is_string($extras)) {
                $append = $extras;
            } elseif (is_array($extras)) {
                $append = array_shift($extras);
            } else {
                $append = print_r($extras, true);
            }
            $message .= ': ' . $append;
        }
        throw new HttpException($code, $message);
    }

    /**
     * 显示flash信息
     *
     * @param string $message 信息显示内容
     * @param mixed $extras 信息显示类型, ['info', 'success', 'error', 'warning']
     * @param integer $code 跳转地址
     * @throws HttpException
     */
    public static function warning($message, $extras = null, $code = 419) {
        if ($extras) {
            if (is_string($extras)) {
                $append = $extras;
            } elseif (is_array($extras)) {
                $append = array_shift($extras);
            } else {
                $append = print_r($extras, true);
            }
            $message .= ': ' . $append;
        }
        throw new HttpException($code, $message);
    }

    /**
     * {@inheritdoc}
     */
    public function afterAction($action, $result) {
        return [
            'code' => 200,
            'msg' => 'Success',
            'data' => parent::afterAction($action, $result),
        ];
    }

}
